package com.atguigu.gmall.product.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.ManagerService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ManagerServiceImpl implements ManagerService {

    private BaseCategory1Mapper baseCategory1Mapper;
    private BaseCategory2Mapper baseCategory2Mapper;
    private BaseCategory3Mapper baseCategory3Mapper;
    private BaseAttrInfoMapper baseAttrInfoMapper;
    private BaseAttrValueMapper baseAttrValueMapper;
    private SpuInfoMapper spuInfoMapper;
    private BaseSaleAttrMapper baseSaleAttrMapper;
    private SpuSaleAttrMapper spuSaleAttrMapper;
    private SpuSaleAttrValueMapper spuSaleAttrValueMapper;
    private SpuImageMapper spuImageMapper;
    private SpuPosterMapper spuPosterMapper;
    private SkuInfoMapper skuInfoMapper;
    private SkuImageMapper skuImageMapper;
    private SkuAttrValueMapper skuAttrValueMapper;
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;
    private BaseCategoryViewMapper baseCategoryViewMapper;
    private RedisTemplate redisTemplate;
    private RedissonClient redissonClient;

    @Autowired
    public ManagerServiceImpl(BaseCategory1Mapper baseCategory1Mapper, BaseCategory2Mapper baseCategory2Mapper, BaseCategory3Mapper baseCategory3Mapper, BaseAttrInfoMapper baseAttrInfoMapper, BaseAttrValueMapper baseAttrValueMapper, SpuInfoMapper spuInfoMapper, BaseSaleAttrMapper baseSaleAttrMapper, SpuSaleAttrMapper spuSaleAttrMapper, SpuSaleAttrValueMapper spuSaleAttrValueMapper, SpuImageMapper spuImageMapper, SpuPosterMapper spuPosterMapper, SkuInfoMapper skuInfoMapper, SkuImageMapper skuImageMapper, SkuAttrValueMapper skuAttrValueMapper, SkuSaleAttrValueMapper skuSaleAttrValueMapper, BaseCategoryViewMapper baseCategoryViewMapper, RedisTemplate redisTemplate, RedissonClient redissonClient) {
        this.baseCategory1Mapper = baseCategory1Mapper;
        this.baseCategory2Mapper = baseCategory2Mapper;
        this.baseCategory3Mapper = baseCategory3Mapper;
        this.baseAttrInfoMapper = baseAttrInfoMapper;
        this.baseAttrValueMapper = baseAttrValueMapper;
        this.spuInfoMapper = spuInfoMapper;
        this.baseSaleAttrMapper = baseSaleAttrMapper;
        this.spuSaleAttrMapper = spuSaleAttrMapper;
        this.spuSaleAttrValueMapper = spuSaleAttrValueMapper;
        this.spuImageMapper = spuImageMapper;
        this.spuPosterMapper = spuPosterMapper;
        this.skuInfoMapper = skuInfoMapper;
        this.skuImageMapper = skuImageMapper;
        this.skuAttrValueMapper = skuAttrValueMapper;
        this.skuSaleAttrValueMapper = skuSaleAttrValueMapper;
        this.baseCategoryViewMapper = baseCategoryViewMapper;
        this.redisTemplate = redisTemplate;
        this.redissonClient = redissonClient;
    }

    // 查询一级分类
    @Override
    public List<BaseCategory1> getCategory1() {
        // 条件设置为 null,表示查询所有
        List<BaseCategory1> baseCategory1List = this.baseCategory1Mapper.selectList(null);
        return baseCategory1List;
    }

    // 根据一级分类 ID 查询二级分类
    @Override
    public List<BaseCategory2> getCategory2(Long category1Id) {
        LambdaQueryWrapper<BaseCategory2> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseCategory2::getCategory1Id, category1Id);

        List<BaseCategory2> baseCategory2List = this.baseCategory2Mapper.selectList(queryWrapper);
        return baseCategory2List;
    }

    @Override
    public List<BaseCategory3> getCategory3(Long category2Id) {
        LambdaQueryWrapper<BaseCategory3> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseCategory3::getCategory2Id, category2Id);
        List<BaseCategory3> baseCategory3List = this.baseCategory3Mapper.selectList(queryWrapper);
        return baseCategory3List;
    }

    @Override
    public List<BaseAttrInfo> attrInfoList(Long category1Id, Long category2Id, Long category3Id) {
        return this.baseAttrInfoMapper.selectAttrInfoList(category1Id, category2Id, category3Id);
    }

    /*
        @Transactional
            默认情况下,只会对运行时异常进行回滚,即 RuntimeException
            但是对于
                IOException 和 SQLException 并不属于 RuntimeException,所以就不会回滚
            所以可以手动指定回滚的级别 rollbackFor = Exception.class
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {
        // 判断当前操作是保存还修改
        if (null != baseAttrInfo.getId()) {
            // 修改平台属性
            this.baseAttrInfoMapper.updateById(baseAttrInfo);
            // 根据平台属性删除属性值集合
            LambdaQueryWrapper<BaseAttrValue> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BaseAttrValue::getAttrId, baseAttrInfo.getId());
            this.baseAttrValueMapper.delete(queryWrapper);
        } else {
            // 保存平台属性
            this.baseAttrInfoMapper.insert(baseAttrInfo);
        }

        // 新增,获取平台属性值集合
        List<BaseAttrValue> attrValueList = baseAttrInfo.getAttrValueList();
        if (!CollectionUtils.isEmpty(attrValueList)) {
            attrValueList.forEach(item -> {
                item.setAttrId(baseAttrInfo.getId());
                this.baseAttrValueMapper.insert(item);
            });
        }
    }

    @Override
    public BaseAttrInfo getAttrInfo(Long attrId) {
        // 获取属性对象
        BaseAttrInfo baseAttrInfo = this.baseAttrInfoMapper.selectById(attrId);
        // 获取属性值集合
        List<BaseAttrValue> list = this.getAttrValueList(attrId);
        // 设置属性值集合
        baseAttrInfo.setAttrValueList(list);
        return baseAttrInfo;
    }

    // 根据属性 ID 查询属性值集合
    private List<BaseAttrValue> getAttrValueList(Long attrId) {
        LambdaQueryWrapper<BaseAttrValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseAttrValue::getAttrId, attrId);
        return this.baseAttrValueMapper.selectList(queryWrapper);
    }

    @Override
    public IPage<SpuInfo> getSpuInfoPage(Page<SpuInfo> spuInfoPage, SpuInfo spuInfo) {
        LambdaQueryWrapper<SpuInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SpuInfo::getCategory3Id, spuInfo.getCategory3Id());
        return this.spuInfoMapper.selectPage(spuInfoPage, queryWrapper);
    }

    @Override
    public List<BaseSaleAttr> baseSaleAttrList() {
        return this.baseSaleAttrMapper.selectList(null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSpuInfo(SpuInfo spuInfo) {
        this.spuInfoMapper.insert(spuInfo);

        // 保存图片
        List<SpuImage> spuImageList = spuInfo.getSpuImageList();
        if (!CollectionUtils.isEmpty(spuImageList)) {
            for (SpuImage spuImage : spuImageList) {
                spuImage.setSpuId(spuInfo.getId());
                this.spuImageMapper.insert(spuImage);
            }
        }

        // 保存海报
        List<SpuPoster> spuPosterList = spuInfo.getSpuPosterList();
        if (!CollectionUtils.isEmpty(spuPosterList)) {
            for (SpuPoster spuPoster : spuPosterList) {
                spuPoster.setSpuId(spuInfo.getId());
                this.spuPosterMapper.insert(spuPoster);
            }
        }

        List<SpuSaleAttr> spuSaleAttrList = spuInfo.getSpuSaleAttrList();
        if (!CollectionUtils.isEmpty(spuSaleAttrList)) {
            for (SpuSaleAttr spuSaleAttr : spuSaleAttrList) {
                spuSaleAttr.setSpuId(spuInfo.getId());
                this.spuSaleAttrMapper.insert(spuSaleAttr);

                List<SpuSaleAttrValue> spuSaleAttrValueList = spuSaleAttr.getSpuSaleAttrValueList();
                if (!CollectionUtils.isEmpty(spuSaleAttrValueList)) {
                    for (SpuSaleAttrValue spuSaleAttrValue : spuSaleAttrValueList) {
                        spuSaleAttrValue.setSpuId(spuInfo.getId());
                        spuSaleAttrValue.setSaleAttrName(spuSaleAttr.getSaleAttrName());
                        this.spuSaleAttrValueMapper.insert(spuSaleAttrValue);
                    }
                }
            }
        }
    }

    @Override
    public List<SpuImage> getSpuImageList(Long spuId) {
        LambdaQueryWrapper<SpuImage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SpuImage::getSpuId, spuId);
        return spuImageMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public List<SpuSaleAttr> getSpuSaleAttrList(Long spuId) {
        return this.spuSaleAttrMapper.selectSpuSaleAttrList(spuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSkuInfo(SkuInfo skuInfo) {
        this.skuInfoMapper.insert(skuInfo);

        List<SkuImage> skuImageList = skuInfo.getSkuImageList();
        if (skuImageList != null && skuImageList.size() > 0) {
            for (SkuImage skuImage : skuImageList) {
                skuImage.setSkuId(skuInfo.getId());
                this.skuImageMapper.insert(skuImage);
            }
        }

        List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfo.getSkuSaleAttrValueList();
        if (!CollectionUtils.isEmpty(skuSaleAttrValueList)) {
            for (SkuSaleAttrValue skuSaleAttrValue : skuSaleAttrValueList) {
                skuSaleAttrValue.setSkuId(skuInfo.getId());
                skuSaleAttrValue.setSpuId(skuInfo.getSpuId());
                this.skuSaleAttrValueMapper.insert(skuSaleAttrValue);
            }
        }

        List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();
        if (!CollectionUtils.isEmpty(skuAttrValueList)) {
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(skuInfo.getId());
                this.skuAttrValueMapper.insert(skuAttrValue);
            }
        }
        // 告知布隆过滤器,存储是否存在的标记到布隆过滤器
        RBloomFilter<Object> bloomFilter = this.redissonClient.getBloomFilter(RedisConst.SKU_BLOOM_FILTER);
        // 添加数据
        bloomFilter.add(skuInfo.getId());
    }

    @Override
    public IPage<SkuInfo> getPage(Page<SkuInfo> pageParam) {
        LambdaQueryWrapper<SkuInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByDesc(SkuInfo::getId);
        return this.skuInfoMapper.selectPage(pageParam, lambdaQueryWrapper);
    }

    @Override
    @Transactional
    public void onSale(Long skuId) {
        SkuInfo skuInfoUp = new SkuInfo();
        skuInfoUp.setId(skuId);
        skuInfoUp.setIsSale(1);
        this.skuInfoMapper.updateById(skuInfoUp);
    }

    @Override
    @Transactional
    public void cancelSale(Long skuId) {
        SkuInfo skuInfoUp = new SkuInfo();
        skuInfoUp.setId(skuId);
        skuInfoUp.setIsSale(0);
        this.skuInfoMapper.updateById(skuInfoUp);
    }

    @Override
    @GmallCache(prefix = "sku:")
    public SkuInfo getSkuInfo(Long skuId) {
        // 最原始解决方案,不添加缓存
        return this.getSkuInfoDB(skuId);

        // 基于 redis 添加缓存,存在问题: 功能可以实现,但是代码太冗余
//        return this.getSkuInfoRedis(skuId);

        // 基于 redisson 添加缓存,
//        return this.getSkuInfoRedisson(skuId);
    }

    /*
        使用 redission 改造 skuInfo 信息获取
     */
    private SkuInfo getSkuInfoRedisson(Long skuId) {
        try {
            // 定义存储 SkuKey,例如 sku:1314:info
            String skuKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;
            // 从缓存中获取数据
            SkuInfo skuInfo = (SkuInfo) this.redisTemplate.opsForValue().get(skuKey);
            // 判断是否获取了数据
            if (null == skuInfo) {
                // 定义锁的 key
                String skuLock = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKULOCK_SUFFIX;
                // 获取锁
                RLock lock = this.redissonClient.getLock(skuLock);
                // 加锁
                boolean res = lock.tryLock(RedisConst.SKUKEY_TIMEOUT, RedisConst.SKULOCK_EXPIRE_PX2, TimeUnit.SECONDS);
                //判断
                if (res) {
                    try {
                        // 获取到了锁,查询数据库
                        skuInfo = this.getSkuInfoDB(skuId);
                        if (skuInfo == null) {
                            // 存储 null,避免缓存穿透
                            skuInfo = new SkuInfo();
                            this.redisTemplate.opsForValue().set(skuKey, skuInfo, RedisConst.SKUKEY_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
                            return skuInfo;
                        } else {
                            // 存储到 redis 中
                            this.redisTemplate.opsForValue().set(skuKey, skuInfo, RedisConst.SKUKEY_TIMEOUT, TimeUnit.SECONDS);
                            return skuInfo;
                        }
                    } finally {
                        // 释放锁
                        lock.unlock();
                    }
                } else {
                    // 没有获取到锁
                    Thread.sleep(100);
                    // 自旋调用
                    return this.getSkuInfoRedisson(skuId);
                }


            } else {
                // 缓存中有数据
                return skuInfo;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 兜底方法
        return this.getSkuInfoDB(skuId);
    }

    /*
        从 redis 中查询 skuInfo 信息(redis 实现分布式锁)
        实现步骤:
            (1)定义存储 SkuInfo 的 key
            (2)根据 SkuKey 获取 SkuInfo 的缓存数据
            (3)判断
                有  => 直接返回数据
                无  =>
                    定义锁的 key
                    尝试加锁
                        加锁失败 => 睡眠并重试自旋
                        加锁成功 => 查询数据库
                            判断是否有值
                                有值 => 直接返回,并缓存到 redis
                                无值 => 创建空值,返回数据
                         释放锁
     */
    public SkuInfo getSkuInfoRedis(Long skuId) {
        try {
            // 定义存储 SkuKey,例如 sku:1314:info
            String skuKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;
            // 尝试获取缓存中的数据(可以直接进行强转,如果存储的是 SkuInfo 对象,那么强转便不会有问题)
            SkuInfo skuInfo = (SkuInfo) this.redisTemplate.opsForValue().get(skuKey);
            // 判断是否有值
            if (null == skuInfo) {
                // 缓存中没有数据
                // 定义锁的 key
                String lockKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKULOCK_SUFFIX;
                // 生成 uuid 标识
                String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                // 获取锁
                Boolean flag = this.redisTemplate.opsForValue().setIfAbsent(lockKey, uuid, RedisConst.SKULOCK_EXPIRE_PX2, TimeUnit.SECONDS);
                // 判断是否获取到了锁
                if (flag) {
                    // 获取到了锁
                    SkuInfo skuInfoDB = this.getSkuInfoDB(skuId);
                    // 判断数据库中是否有值
                    if (null == skuInfoDB) {
                        // 存储空值
                        SkuInfo skuInfo1 = new SkuInfo();
                        this.redisTemplate.opsForValue().set(skuKey, skuInfo1, RedisConst.SKUKEY_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
                        return skuInfo1;
                    }
                    // 数据库查询的数据不为空
                    // 存储缓存
                    this.redisTemplate.opsForValue().set(skuKey, skuInfoDB, RedisConst.SKUKEY_TIMEOUT, TimeUnit.SECONDS);

                    // 释放锁,使用 lua 脚本
                    String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                            "then\n" +
                            "    return redis.call(\"del\",KEYS[1])\n" +
                            "else\n" +
                            "    return 0\n" +
                            "end";
                    // 创建脚本对象
                    DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript<>();
                    // 设置脚本
                    defaultRedisScript.setScriptText(script);
                    // 设置返回值类型
                    defaultRedisScript.setResultType(Long.class);

                    // 执行删除
                    this.redisTemplate.execute(defaultRedisScript, Arrays.asList(lockKey), uuid);

                    return skuInfoDB;
                } else {
                    // 没有获取锁
                    Thread.sleep(100);
                    // 自旋调用
                    this.getSkuInfoRedis(skuId);
                }
            } else {
                // 缓存中有数据,直接返回即可
                return skuInfo;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 兜底 => 如果在上面从缓存中获取的过程中出现异常,那么这行代码必须执行
        return this.getSkuInfoDB(skuId);
    }

    // 从数据库中查询 skuInfo 信息
    public SkuInfo getSkuInfoDB(Long skuId) {
        SkuInfo skuInfo = this.skuInfoMapper.selectById(skuId);
        LambdaQueryWrapper<SkuImage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SkuImage::getSkuId, skuId);
        List<SkuImage> skuImageList = this.skuImageMapper.selectList(lambdaQueryWrapper);
        if (null != skuInfo) {
            skuInfo.setSkuImageList(skuImageList);
        }
        return skuInfo;
    }

    @Override
    @GmallCache(prefix = "categoryVie:")
    public BaseCategoryView getCategoryViewByCategory3Id(Long category3Id) {
        return this.baseCategoryViewMapper.selectById(category3Id);
    }

    /*
      对于价格,不需要从缓存中读取,而是直接从数据库中进行读取,是否要添加分布式锁
        需要 => 添加分布式锁后,当大量请求过来时,可以保证一条一条的访问数据库,防止造成数据库访问压力过大造成宕机(相当于流控)
        不需要 => 流控并不一定需要使用分布式锁,分布式锁效率太低,也可以使用 rabbitmq 的消息队列等其他方式实现
     */
    @Override
    public BigDecimal getSkuPrice(Long skuId) {
        // 获取锁
        RLock lock = this.redissonClient.getLock(skuId + ":lock");

        try {
            // 加锁
            lock.lock();

            SkuInfo skuInfo = this.skuInfoMapper.selectById(skuId);
            if (null != skuInfo) {
                return skuInfo.getPrice();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放锁
            lock.unlock();
        }
        return new BigDecimal("0");
    }

    @Override
    @GmallCache(prefix = "spuSaleAttrListCheckBySku:")
    public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId) {
        return this.spuSaleAttrMapper.selectSpuSaleAttrListCheckBySku(skuId, spuId);
    }

    @Override
    @GmallCache(prefix = "skuValueIdsMap:")
    public Map getSkuValueIdsMap(Long spuId) {
        Map<Object, Object> map = new HashMap<>();
        List<Map> mapList = this.skuSaleAttrValueMapper.selectSaleAttrValuesBySpu(spuId);
        if (mapList != null && mapList.size() > 0) {
            for (Map skuMap : mapList) {
                map.put(skuMap.get("value_ids"), skuMap.get("sku_id"));
            }
        }
        return map;
    }

    @Override
    @GmallCache(prefix = "spuPosterBySpuId:")
    public List<SpuPoster> findSpuPosterBySpuId(Long spuId) {
        LambdaQueryWrapper<SpuPoster> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SpuPoster::getSpuId, spuId);
        return spuPosterMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    @GmallCache(prefix = "attrList:")
    public List<BaseAttrInfo> getAttrList(Long skuId) {
        return this.baseAttrInfoMapper.selectBaseAttrInfoListBySkuId(skuId);
    }

    // 首页数据查询三级分类数据
    @Override
    @GmallCache(prefix = "category")
    public List<JSONObject> getBaseCategoryList() {
        // 声明 json 集合
        ArrayList<JSONObject> list = new ArrayList<>();
        // 声明获取所有分类数据集合
        List<BaseCategoryView> baseCategoryViewList = baseCategoryViewMapper.selectList(null);
        // 循环上面的集合并安一级分类 Id 进行分组
        Map<Long, List<BaseCategoryView>> category1Map  = baseCategoryViewList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));
        int index = 1;
        // 获取一级分类下所有数据
        for (Map.Entry<Long, List<BaseCategoryView>> entry1  : category1Map.entrySet()) {
            // 获取一级分类 Id
            Long category1Id  = entry1.getKey();
            // 获取一级分类下面的所有集合
            List<BaseCategoryView> category2List1  = entry1.getValue();
            JSONObject category1 = new JSONObject();
            category1.put("index", index);
            category1.put("categoryId",category1Id);
            // 一级分类名称
            category1.put("categoryName",category2List1.get(0).getCategory1Name());
            // 变量迭代
            index++;
            // 循环获取二级分类数据
            Map<Long, List<BaseCategoryView>> category2Map  = category2List1.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
            // 声明二级分类对象集合
            List<JSONObject> category2Child = new ArrayList<>();
            // 循环遍历
            for (Map.Entry<Long, List<BaseCategoryView>> entry2  : category2Map.entrySet()) {
                // 获取二级分类 Id
                Long category2Id  = entry2.getKey();
                // 获取二级分类下的所有集合
                List<BaseCategoryView> category3List  = entry2.getValue();
                // 声明二级分类对象
                JSONObject category2 = new JSONObject();
                category2.put("categoryId",category2Id);
                category2.put("categoryName",category3List.get(0).getCategory2Name());
                // 添加到二级分类集合
                category2Child.add(category2);
                List<JSONObject> category3Child = new ArrayList<>();

                // 循环三级分类数据
                category3List.stream().forEach(category3View -> {
                    JSONObject category3 = new JSONObject();
                    category3.put("categoryId",category3View.getCategory3Id());
                    category3.put("categoryName",category3View.getCategory3Name());
                    category3Child.add(category3);
                });
                // 将三级数据放入二级里面
                category2.put("categoryChild",category3Child);
            }
            // 将二级数据放入一级里面
            category1.put("categoryChild",category2Child);
            list.add(category1);
        }
        return list;
    }
}
